# -*- coding: UTF-8 -*-
from django.db import models
from django.contrib.auth.models import User
import re
from datetime import datetime

class Player(models.Model):
    name        = models.CharField(max_length=200)

    def __unicode__(self):
        return self.name

    def get_planets(self):
        return Planet.objects.filter(player=self)

class Planet(models.Model):
    player      = models.ForeignKey(Player)
    name        = models.CharField(max_length=200)
    galaxy      = models.IntegerField()
    ss          = models.IntegerField()
    position    = models.IntegerField()
    last_update = models.DateTimeField()

    def __unicode__(self):
        return '%d:%d:%d (%s owned by %s)' % (self.galaxy, self.ss, self.position, self.name, self.player)

    def get_reports(self):
        return Report.objects.filter(planet=self).order_by('-report_date')

    def get_last_report(self):
        return Report.objects.filter(planet=self).order_by('-report_date')[0]

    class Meta:
        ordering    = ['galaxy','ss','position']

class Report(models.Model):
    date                = models.DateTimeField(auto_now_add=True)
    user                = models.ForeignKey(User)
    planet              = models.ForeignKey(Planet)
    raw_report          = models.TextField()
    report_date         = models.DateTimeField()
    contain_research    = models.BooleanField(default=False)
    contain_resource    = models.BooleanField(default=False)
    contain_ship        = models.BooleanField(default=False)
    contain_defense     = models.BooleanField(default=False)
    contain_bomb        = models.BooleanField(default=False)
    contain_army        = models.BooleanField(default=False)
    contain_construction= models.BooleanField(default=False)

    def __unicode__(self):
        return '%d:%d:%d at %s by %s' % (self.planet.galaxy, self.planet.ss, self.planet.position, self.report_date, self.user)

    def get_constructions(self):
        return Construction.objects.filter(report=self)

    def get_researches(self):
        return Research.objects.filter(report=self)

    def get_resources(self):
        return Resource.objects.filter(report=self)

    def get_army(self):
        return Army.objects.filter(report=self)

    def get_resource(self, resource_name):
        basic_resources = {
            'iron':     'Fer',
            'gold':     'Or',
            'crystal':  'Cristal',
            'hydrogene':'Hydrogène',
        }
        army            = {
            'technicien':   'Techniciens',
        }
        if resource_name in basic_resources:
            try:
                return Resource.objects.get(report__id=self.pk, resource=basic_resources[resource_name]).quantity
            except:
                return 0
        else:
            try:
                lu = LandUnit.objects.filter(name=army[resource_name])
                return Army.objects.get(report=self, unit=lu).quantity
            except:
                pass
            return 0

    @staticmethod
    def is_duplicate(date, planet_coord):
        r       = Report.objects.filter(report_date=date)
        for t in r:
            if int(t.planet.galaxy) != int(planet_coord[0]):
                continue
            if int(t.planet.ss) != int(planet_coord[1]):
                continue
            if int(t.planet.position) != int(planet_coord[2]):
                continue
            return True

        return False

    @staticmethod
    def parse(str, user):
        reports         = []

        ignore          = False

        buildings       = {}
        tmp_buildings   = Building.objects.all()
        for building in tmp_buildings:
            buildings[building.name] = building

        technologies    = {}
        tmp_technologies= Technology.objects.all()
        for techno in tmp_technologies:
            technologies[techno.name] = techno

        land_units      = {}
        tmp_land_unit   = LandUnit.objects.all()
        for lu in tmp_land_unit:
            land_units[lu.name] = lu

        spe_engines     = {}
        tmp_spe_engines = SpecializedEngine.objects.all()
        for se in tmp_spe_engines:
            spe_engines[se.name]    = se

        militaries      = {}
        tmp_militaries  = Military.objects.all()
        for m in tmp_militaries:
            militaries[m.name] = m

        regex   = '^(\d{2})\/(\d{2})\/(\d{4}) (\d{2}):(\d{2}):(\d{2})\s+Rapport d\'espionnage de la plan.te (\S+)'
        regex   +='\[(\d+):(\d+):(\d+)\] du joueur (\S+)\s*$'

        regex   = '^(\d{2})\/(\d{2})\/(\d{4}) (\d{2}):(\d{2}):(\d{2})\s+Rapport d\'espionnage de la plan.te ([^\[]+)\s*\[(\d+):(\d+):(\d+)\] du joueur (\S+)\s*$'
        current_category    = None
        i = 0
        raw_report  = ''
        for line in str.split("\n"):
            raw_report += line + "\n"
            i += 1
            line = line.strip()
            if len(line) == 0:
                continue
            if line[0] == '-':
                types   = {
                    u'Zone':        'research',
                    u'Laboratoire': 'research',
                    u'Ressources':  'resource',
                    u'Vaisseaux':   'ship',
                    u'Défenses':    'defense',
                    u'Bombe':       'bombe',
                    u'Militaires':  'army',
                    u'Bâtiments':   'construction',
                }
                category = line[2:].strip().split(' ')[0]
                current_category = types.get(category)
                setattr(self, 'contain_%s' % current_category, True)
            elif line[0].isalpha() and ignore is False:
                try:
                    if self is None:
                        continue
                except UnboundLocalError:
                    continue
                data    = line.split(':')
                if len(data) == 1:
                    continue
                key     = data[0].strip()
                try:
                    value   = int(data[1].strip())
                except ValueError:
                    try:
                        value   = int(data[1].strip().replace('.', ''))
                    except:
                        continue

                if current_category == 'research':
                    techno  = technologies.get(key)
                    if techno is None:
                        techno      = Technology()
                        techno.name = key
                        techno.save()
                        technologies[key] = techno
                    research            = Research()
                    research.player     = player
                    research.technology = techno
                    research.level      = value
                    research.report     = self
                    research.save()
                elif current_category == 'resource':
                    res                 = Resource()
                    res.resource        = key
                    res.quantity        = value
                    res.report          = self
                    res.save()
                elif current_category == 'army':
                    lu                  = land_units.get(key)
                    if lu is None:
                        lu              = LandUnit()
                        lu.name         = key
                        lu.save()
                        land_units[key] = lu
                    army                = Army()
                    army.unit           = lu
                    army.report         = self
                    army.quantity       = value
                    army.planet         = planet
                    army.save()
                elif current_category == 'army':
                    m       = militaries.get(key)
                    if m is None:
                        m       = Military()
                        m.name  = key
                        m.save()
                        militaries[key] = m
                    c           = Crew()
                    c.military  = m
                    c.report    = self
                    c.quantity  = value
                    c.save()
                elif current_category == 'construction':
                    b   = buildings.get(key)
                    if b is None:
                        b       = Building()
                        b.name  = key
                        b.save()
                        buildings[key] = b
                    c           = Construction()
                    c.building  = b
                    c.level     = value
                    c.planet    = planet
                    c.report    = self
                    c.save()
            else:
                result = re.search(regex, line)
                if result is not None:
                    if len(result.groups()) > 0:
                        try:
                            self.raw_report = raw_report
                            self.save()
                            raw_report      = ''
                        except:
                            pass
                        self            = Report()
                        current_category= None
                        groups          = result.groups()
                        date_report     = datetime(int(groups[2]), int(groups[1]), int(groups[0]), int(groups[3]), int(groups[4]), int(groups[5]))


                        self.report_date= date_report
                        self.user       = user
                        planet_name     = groups[6]
                        coord           = (groups[7], groups[8], groups[9])
                        player_name     = groups[10]

                        ignore  = Report.is_duplicate(date_report, coord)
                        if ignore is True:
                            continue

                        reports.append(self)
                        try:
                            player      = Player.objects.get(name=player_name)
                        except:
                            player      = Player()
                            player.name = player_name
                            player.save()
                        try:
                            planet      = Planet.objects.get(galaxy=coord[0], ss=coord[1], position=coord[2])
                            planet.last_update = date_report
                            planet.save()
                        except:
                            planet          = Planet()
                            planet.name     = planet_name
                            planet.galaxy   = coord[0]
                            planet.ss       = coord[1]
                            planet.position = coord[2]
                            planet.player   = player
                            planet.last_update = date_report
                            planet.save()


                        self.planet = planet
                        self.save()

        try:
            self.raw_report = raw_report
            self.save()
        except:
            pass
        return reports

class Player(models.Model):
    name        = models.CharField(max_length=200, unique=True)

    def __unicode__(self):
        return self.name

class Technology(models.Model):
    name        = models.CharField(max_length=200)

    def __unicode__(self):
        return self.name

class SpecializedEngine(models.Model):
    name        = models.CharField(max_length=200)

    def __unicode__(self):
        return self.name

class LandUnit(models.Model):
    name        = models.CharField(max_length=200)

    def __unicode__(self):
        return self.name

class Building(models.Model):
    name        = models.CharField(max_length=200)

    def __unicode__(self):
        return self.name

class Army(models.Model):
    unit        = models.ForeignKey(LandUnit)
    quantity    = models.IntegerField()
    report      = models.ForeignKey(Report)

    def __unicode__(self):
        return '%d %s on %d:%d:%d' % (self.quantity, self.unit.name, self.report.planet.galaxy, self.report.planet.ss, self.report.planet.position)

class Research(models.Model):
    technology  = models.ForeignKey(Technology)
    level       = models.IntegerField()
    report      = models.ForeignKey(Report)

    def __unicode__(self):
        return '%s level %d for %s' % (self.technology.name, self.level, self.report.planet.player)

class Construction(models.Model):
    building    = models.ForeignKey(Building)
    level       = models.IntegerField()
    report      = models.ForeignKey(Report)

    def __unicode__(self):
        return '%s level %d on %d:%d:%d' % (self.building.name, self.level, self.report.planet.galaxy, self.report.planet.ss, self.report.planet.position)

class Resource(models.Model):
    resource    = models.CharField(max_length=30)
    quantity    = models.IntegerField()
    report      = models.ForeignKey(Report)

    def __unicode__(self):
        return '%d %s on %d:%d:%d' % (self.quantity, self.resource, self.report.planet.galaxy, self.report.planet.ss, self.report.planet.position)

class Military(models.Model):
    name        = models.CharField(max_length=200)

    def __unicode__(self):
        return self.name

class Crew(models.Model):
    military    = models.ForeignKey(Military)
    quantity    = models.IntegerField()
    report      = models.ForeignKey(Report)
    report      = models.ForeignKey(Report)

